home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / STK100.ZIP / PLAYDWM.PAS < prev    next >
Pascal/Delphi Source File  |  1995-01-12  |  12KB  |  488 lines

  1. (******************************************************************************
  2. File:              playdwm.pas
  3. Tab stops:                 every 2 collumns
  4. Project:                     DWM Player
  5. Copyright:                 1994 DiamondWare, Ltd.  All rights reserved.*
  6. Written:                     Keith Weiner & Erik Lorenzen
  7. Pascal Conversion: David A. Johndrow
  8. Purpose:                     Contains simple example code to show how to load/play a
  9.                                      .DWM file
  10. History:                     KW 10/21/94 Started playdwm.c
  11.                                      DJ 11/12/94 Translated to Pascal
  12.                                      EL 01/12/95 Finalized
  13.  
  14. Notes
  15. -----
  16.  
  17. The bulk of this file is error checking logic.
  18.  
  19. However, this code isn't really robust when it comes to standard error checking
  20. and particularly recovery, software engineering technique, etc. The STK will
  21. handle songs larger than 64K (but not digitized sounds).    Also, exitting
  22. and cleanup is not handled robustly in this code.  The code below can
  23. only be validated by extremely careful scrutiny to make sure each case is
  24. handled properly.
  25.  
  26. But all such code would make this example file less clear; its purpose was
  27. to illustrate how to call the STK, not how to write QA-proof software.
  28.  
  29.  
  30. *Permission is expressely granted to use DisplayError or any derivitive made
  31.  from it to registered users of the STK.
  32. ******************************************************************************)
  33.  
  34.  
  35.  
  36. Program PlayDWM;
  37.  
  38. uses crt,dws;
  39.  
  40.  
  41.  
  42. var
  43.     ExitSave: pointer;
  44.  
  45.     song:              pointer;
  46.     fp:                  file;
  47.     dov:                 dws_DOPTR;
  48.     dres:              dws_DRPTR;
  49.     ideal:             dws_IDPTR;
  50.     mplay:             dws_MPPTR;
  51.     ch:                  char;
  52.     musvol:          word;
  53.     errno:             word;
  54.     songplaying: word;
  55.     songsize:      longint;
  56.  
  57.  
  58.  
  59. Procedure DisplayError;
  60. begin
  61.     case dws_ErrNo of
  62.  
  63.         dws_EZERO:
  64.         begin
  65.             (*
  66.              . This should not have happened, considering how we got here!
  67.             *)
  68.             writeln('I am confused!  Where am I?  HOW DID I GET HERE????');
  69.             writeln('The ERROR number is:',dws_ErrNo);
  70.         end;
  71.  
  72.         dws_NOTINITTED:
  73.         begin
  74.             (*
  75.              . If we get here, it means you haven't called dws_Init().
  76.              . The STK needs to initialize itself and the hardware before
  77.              . it can do anything.
  78.             *)
  79.             writeln('The STK was not initialized');
  80.         end;
  81.  
  82.         dws_ALREADYINITTED:
  83.         begin
  84.             (*
  85.              . If we get here, it means you've called dws_Init() already.  Calling
  86.              . dws_DetectHardWare() at this point would cause zillions of
  87.              . problems if we let the call through.
  88.             *)
  89.             writeln('The STK was already initialized');
  90.         end;
  91.  
  92.         dws_NOTSUPPORTED:
  93.         begin
  94.             (*
  95.              . If we get here, it means that either the user's machine does not
  96.              . support the function you just called, or the STK was told not to
  97.              . support it in dws_Init.
  98.             *)
  99.             writeln('Function not supported');
  100.         end;
  101.  
  102.         dws_DetectHardware_UNSTABLESYSTEM:
  103.         begin
  104.             (*
  105.              . Please report it to DiamondWare if you get here!
  106.              .
  107.              . Ideally, you would disable control-C here, so that the user can't
  108.              . hit control-alt-delete, causing SmartDrive to flush its (possibly
  109.              . currupt) buffers.
  110.             *)
  111.             writeln('The system is unstable!');
  112.             writeln('Please power down now!');
  113.  
  114.             while (1 = 1) do
  115.             begin
  116.             end;
  117.         end;
  118.  
  119.         (*
  120.          . The following three errors are USER/PROGRAMMER errors.  You forgot
  121.          . to fill the cardtyp struct full of -1's (except in those fields
  122.          . you intended to override, or the user (upon the unlikly event that
  123.          . the STK was unable to find a card) gave you a bad overide value.
  124.         *)
  125.         dws_DetectHardware_BADBASEPORT:
  126.         begin
  127.             (*
  128.              . You set dov.baseport to a bad value, or
  129.              . didn't fill it with a -1.
  130.             *)
  131.             writeln('Bad port address');
  132.         end;
  133.  
  134.         dws_DetectHardware_BADDMA:
  135.         begin
  136.             (*
  137.              . You set dov.digdma to a bad value, or
  138.              . didn't fill it with a -1.
  139.             *)
  140.             writeln('Bad DMA channel');
  141.         end;
  142.  
  143.         dws_DetectHardware_BADIRQ:
  144.         begin
  145.             (*
  146.              . You set dov.digirq to a bad value, or
  147.              . didn't fill it with a -1.
  148.             *)
  149.             writeln('Bad IRQ level');
  150.         end;
  151.  
  152.         dws_Kill_CANTUNHOOKISR:
  153.         begin
  154.             (*
  155.              . The STK points the interrupt vector for the sound card's IRQ
  156.              . to its own code in dws_Init.
  157.              .
  158.              . dws_Kill was unable to restore the vector to its original
  159.              . value because other code has hooked it after the STK
  160.              . initialized(!)  This is really bad.    Make the user get rid
  161.              . of it and call dws_Kill again.
  162.             *)
  163.             writeln('Get rid of your TSR, pal!');
  164.             writeln('(Press any key)');
  165.             repeat
  166.             until (keypressed);
  167.         end;
  168.  
  169.         dws_X_BADINPUT:
  170.         begin
  171.             (*
  172.              . The mixer funtion's can only accept volumes between 0 & 255,
  173.              . the volume will remain unchanged.
  174.             *)
  175.             writeln('Bad mixer level');
  176.         end;
  177.  
  178.         dws_D_NOTADWD:
  179.         begin
  180.             (* You passed the STK a pointer to something which is not a .DWD file! *)
  181.             writeln('The file you are attempting to play is not a .DWD');
  182.         end;
  183.  
  184.         dws_D_NOTSUPPORTEDVER:
  185.         begin
  186.             (*
  187.              . The STK can't play a .DWD converted using a version of VOC2DWD.EXE
  188.              . newer than itself.  And, although we'll try to maintain backwards
  189.              . compatibility, we may not be able to guarantee that newer versions
  190.              . of the code will be able to play older .DWD files.  In any event,
  191.              . it's a good idea to always convert .VOC files with the utility
  192.              . which comes with the library you're linking into your application.
  193.             *)
  194.             writeln('Please reconvert this file using the VOC2DWD.EXE which came with this library');
  195.         end;
  196.  
  197.         dws_D_INTERNALERROR:
  198.         begin
  199.             (*
  200.              . This error should never occur and probably will not affect sound
  201.              . play(?).  If it happens please contact DiamondWare.
  202.             *)
  203.             writeln('An internal error has occured');
  204.             writeln('Please contact DiamondWare');
  205.         end;
  206.  
  207.         dws_DPlay_NOSPACEFORSOUND:
  208.         begin
  209.             (*
  210.              . This error is more like a warning, though it may happen on a
  211.              . regular basis, depending on how many sounds you told the STK
  212.              . to allow in dws_Init, how you chose to prioritize sounds and
  213.              . how many sounds are currently being played.
  214.             *)
  215.             writeln('No more room for new digitized sounds right now');
  216.         end;
  217.  
  218.         dws_DSetRate_FREQTOLOW:
  219.         begin
  220.             (*
  221.              . The STK will set rate as close as possible to the indicated rate
  222.              . but cannot set a rate that low.
  223.             *)
  224.             writeln('Playback frequency too low');
  225.         end;
  226.  
  227.         dws_DSetRate_FREQTOHIGH:
  228.         begin
  229.             (*
  230.              . The STK will set rate as close as possible to the indicated rate
  231.              . but cannot set a rate that high.
  232.             *)
  233.             writeln('Playback frequency too high');
  234.         end;
  235.  
  236.         dws_MPlay_NOTADWM:
  237.         begin
  238.             (* You passed the STK a pointer to something which is not a .DWM file! *)
  239.             writeln('The file you are attempting to play is not a .DWM');
  240.         end;
  241.  
  242.         dws_MPlay_NOTSUPPORTEDVER:
  243.         begin
  244.             (*
  245.              . The STK can't play a .DWM converted using a version of VOC2DWM.EXE
  246.              . newer than itself.  And, although we'll try to maintain backwards
  247.              . compatibility, we may not be able to guarantee that newer versions
  248.              . of the code will be able to play older .DWM files.  In any event,
  249.              . it's a good idea to always convert .MID files with the utility
  250.              . which comes with the library you're linking into your application.
  251.             *)
  252.             writeln('Please reconvert this file using the MID2DWM.EXE which came with this library');
  253.         end;
  254.  
  255.         dws_MPlay_INTERNALERROR:
  256.         begin
  257.             (*
  258.              . This error should never occur and probably will not affect sound
  259.              . play(?). If it happens please contact DiamondWare.
  260.             *)
  261.             writeln('An internal error has occured.');
  262.             writeln('Please contact DiamondWare');
  263.         end;
  264.  
  265.         else
  266.         begin
  267.             (*
  268.              . This should never occur and probably will not affect sound
  269.              . play(?). If it happens please contact DiamondWare.
  270.             *)
  271.             writeln('I am confused!  Where am I?  HOW DID I GET HERE????');
  272.             writeln('The ERROR number is:',dws_ErrNo);
  273.         end;
  274.     end;
  275. end;
  276.  
  277.  
  278.  
  279. procedure ExitPlay; far;
  280.  
  281. label TRYTOKILLAGAIN;
  282.  
  283. begin
  284.     ExitProc := ExitSave;
  285.  
  286.     dwt_Kill;
  287.  
  288. TRYTOKILLAGAIN:
  289.  
  290.     if (dws_Kill <> 1) then
  291.     begin
  292.         (*
  293.          . If an error occurs here, it's either dws_Kill_CANTUNHOOKISR
  294.          . or dws_NOTINITTED.  If it's dws_Kill_CANTUNHOOKISR the user
  295.          . must remove his tsr, and dws_Kill must be called again.    If it's
  296.          . dws_NOTINITTED, there's nothing to worry about at this point.
  297.         *)
  298.         DisplayError;
  299.  
  300.         if (dws_ErrNo = dws_Kill_CANTUNHOOKISR) then
  301.         begin
  302.             goto TRYTOKILLAGAIN;
  303.         end;
  304.     end;
  305.  
  306.     if (song <> nil) then
  307.     begin
  308.         freemem(song, songsize);
  309.     end;
  310.  
  311.     dispose(mplay);
  312.     dispose(ideal);
  313.     dispose(dres);
  314.     dispose(dov);
  315.  
  316. end;
  317.  
  318.  
  319.  
  320. Function Exist(FileName: string): boolean;
  321. Var
  322.     Fil: File;
  323.  
  324. begin
  325.     Assign(Fil,FileName);
  326.     {$I- }
  327.     Reset(Fil);
  328.     Close(Fil);
  329.     {$I+ }
  330.  
  331.     Exist := (IOResult = 0);
  332. end;
  333.  
  334.  
  335. begin
  336.     ExitSave := ExitProc;
  337.     ExitProc := @ExitPlay;
  338.  
  339.     writeln;
  340.     writeln('PLAYDWM is Copyright 1994, DiamondWare, Ltd.');
  341.     writeln('All rights reserved.');
  342.     writeln;
  343.     writeln;
  344.  
  345.     new(dov);
  346.     new(dres);
  347.     new(ideal);
  348.     new(mplay);
  349.  
  350.     song     := nil;
  351.     musvol := 255; (* Default mxr volume at startup is max *)
  352.     ch         := '0';
  353.  
  354.     if (ParamCount = 0) then
  355.     begin
  356.         writeln('Usage PLAYDWM <dwm-file>');
  357.         halt(65535);
  358.     end;
  359.  
  360.     if Exist(ParamStr(1)) then
  361.     begin
  362.         Assign(fp, ParamStr(1));
  363.         Reset(fp,1);
  364.         songsize := filesize(fp);
  365.  
  366.         (* Please note we don't check to see if we get the memory we need. *)
  367.         Getmem(song, songsize);
  368.         BlockRead(fp,song^,songsize);
  369.  
  370.         Close(fp);
  371.     end
  372.     else
  373.     begin
  374.         writeln('Unable to open '+ParamStr(1));
  375.         halt(65535);
  376.     end;
  377.  
  378.     (*
  379.      . We need to set every field to -1 in dws_DETECTOVERRIDES record; this
  380.      . tells the STK to autodetect everything.    Any other value
  381.      . overrides the autodetect routine, and will be accepted on
  382.      . faith, though the STK will verify it if possible.
  383.     *)
  384.     dov^.baseport := 65535;
  385.     dov^.digdma     := 65535;
  386.     dov^.digirq     := 65535;
  387.  
  388.     if (dws_DetectHardWare(dov, dres) = 0) then
  389.     begin
  390.         DisplayError;
  391.         halt(65535);
  392.     end;
  393.  
  394.     (*
  395.      . The "ideal" record tells the STK how you'd like it to initialize the
  396.      . sound hardware.    In all cases, if the hardware won't support your
  397.      . request, the STK will go as close as possible.  For example, not all
  398.      . sound boards will support al sampling rates (some only support 5 or
  399.      . 6 discrete rates).
  400.     *)
  401.     ideal^.musictyp     := 1;         (*for now, it's OPL2 music*)
  402.     ideal^.digtyp         := 0;         (*0=No Dig, 8=8bit, 16=16bit*)
  403.     ideal^.digrate        := 0;         (*sampling rate, in Hz*)
  404.     ideal^.dignvoices := 0;         (*number of voices (up to 16)*)
  405.     ideal^.dignchan     := 0;         (*1=mono, 2=stereo*)
  406.  
  407.     if (dws_Init(dres, ideal) = 0) then
  408.     begin
  409.         DisplayError;
  410.         halt(65535);
  411.     end;
  412.  
  413.     (*
  414.      .    72.8Hz is a decent compromise.    It will work in a Windows DOS box
  415.      .    without any problems, and yet it allows music to sound pretty good.
  416.      .    In my opinion, there's no reason to go lower than 72.8 (unless you
  417.      .    don't want the hardware timer reprogrammed)--music sounds kinda chunky
  418.      .    at lower rates.  You can go to 145.6 Hz, and get smoother (very
  419.      .    subtly) sounding music, at the cost that it will NOT run at the correct
  420.      .    (or constant) speed in a Windows DOS box.}
  421.     *)
  422.  
  423.     dwt_Init(dwt_72_8HZ);
  424.  
  425.     (*
  426.      . Set music volume to about 4/5ths max
  427.     *)
  428.     musvol := 200;
  429.  
  430.     if (dws_XMusic(musvol) = 0) then
  431.     begin
  432.         DisplayError;
  433.     end;
  434.  
  435.     mplay^.track := song;
  436.     mplay^.count := 1;
  437.  
  438.     if (dws_MPlay(mplay) = 0) then
  439.     begin
  440.         DisplayError;
  441.         halt(65535);
  442.     end;
  443.  
  444.     (*
  445.      . We're playing.  Let's exit when the song is over, and allow the user
  446.      . to fiddle with the volume level (mixer) in the meantime
  447.     *)
  448.     writeln('Press + or - to change playback volume ');
  449.  
  450.     repeat
  451.     begin
  452.         if(dws_MSongStatus(@songplaying) = 0) then
  453.         begin
  454.             DisplayError;
  455.             halt(65535);
  456.         end;
  457.  
  458.         if Keypressed then begin
  459.             ch := readkey;
  460.             case ord(ch) of
  461.                 43:
  462.                 begin
  463.                     inc(musvol);
  464.                     writeln('Music Volume is ', musvol);
  465.  
  466.                     if (dws_XMusic(musvol) = 0) then
  467.                     begin
  468.                         DisplayError;
  469.                     end;
  470.                 end;
  471.                 45:
  472.                 begin
  473.                     dec(musvol);
  474.                     writeln('Music Volume is ', musvol);
  475.  
  476.                     if (dws_XMusic(musvol) = 0) then
  477.                     begin
  478.                         DisplayError;
  479.                     end;
  480.                 end;
  481.             end;
  482.         end;
  483.     end;
  484.     until (songplaying = 0) or (ch = 'q') or (ch = 'Q') or (ch = chr(27));
  485.  
  486.     halt(65535);
  487. end.
  488.